import { defineStore } from 'pinia'
import { storage } from '../utils/storage'
import { RouteRecordRaw } from 'vue-router'
import { fetchUserPermissions, fetchButtonPermissions, fetchMenuTree } from '../api/permission'
import { ElMessage } from 'element-plus'

/**
 * 权限状态接口
 */
interface PermissionState {
  permissions: string[]
  accessRoutes: RouteRecordRaw[]
  menuTree: any[]
  buttonPermissions: Record<string, string[]>
  loadedMenuIds: Set<string | number>
  isLoadingPermissions: boolean
}

/**
 * 菜单项接口
 */
interface MenuItem {
  id: number | string
  name: string
  code: string
  type: string
  path?: string
  component?: string
  icon?: string
  children?: MenuItem[]
  keepAlive?: boolean
  show?: boolean
  order?: number
  hidden?: boolean
}

// 扩展RouteRecordRaw类型，允许component为函数
interface CustomRouteRecordRaw extends Omit<RouteRecordRaw, 'component' | 'children'> {
  component?: any
  children?: CustomRouteRecordRaw[]
}

// 全局权限请求Promise
let permissionsPromise: Promise<any> | null = null;

export const usePermissionStore = defineStore('permission', {
  state: (): PermissionState => ({
    permissions: storage.get('permissions') || [],
    accessRoutes: [],
    menuTree: storage.get('menuTree') || [],
    buttonPermissions: {},
    loadedMenuIds: new Set(),
    isLoadingPermissions: false
  }),
  
  getters: {
    getPermissions: (state) => state.permissions,
    getAccessRoutes: (state) => state.accessRoutes,
    getMenuTree: (state) => state.menuTree,
    getButtonPermissions: (state) => state.buttonPermissions,
    
    /**
     * 检查是否有指定权限
     * @param permission 权限标识
     * @returns boolean
     */
    hasPermission: (state) => (permission: string) => {
      if (!permission) return true
      return state.permissions.includes('*') || state.permissions.includes(permission)
    },
    
    /**
     * 检查是否有指定权限中的任意一个
     * @param permissions 权限标识数组
     * @returns boolean
     */
    hasAnyPermission: (state) => (permissions: string[]) => {
      if (!permissions || permissions.length === 0) return true
      return state.permissions.includes('*') || permissions.some(p => state.permissions.includes(p))
    },
    
    /**
     * 检查是否有指定权限中的所有权限
     * @param permissions 权限标识数组
     * @returns boolean
     */
    hasAllPermissions: (state) => (permissions: string[]) => {
      if (!permissions || permissions.length === 0) return true
      return state.permissions.includes('*') || permissions.every(p => state.permissions.includes(p))
    },
    
    /**
     * 检查是否有指定按钮权限
     * @param menuPath 菜单路径
     * @param buttonKey 按钮权限标识
     * @returns boolean
     */
    hasButtonPermission: (state) => (menuPath: string, buttonKey: string) => {
      if (!menuPath || !buttonKey) return false
      if (state.permissions.includes('*')) return true
      
      const menuButtons = state.buttonPermissions[menuPath] || []
      return menuButtons.includes(buttonKey)
    }
  },
  
  actions: {
    /**
     * 加载用户权限
     * 分别获取权限树（包含按钮权限）和菜单树（只包含菜单）
     */
    async loadPermissions() {
      // 如果已有缓存的请求，直接返回
      if (permissionsPromise) return permissionsPromise
      
      this.isLoadingPermissions = true
      
      permissionsPromise = Promise.all([
        // 获取用户权限列表（扁平化权限数组）
        fetchUserPermissions().catch(error => {
          console.error('[PermissionStore] 加载用户权限失败:', error)
          return { code: 200, data: { permissions: [] } }
        }),
        // 获取菜单树（只包含菜单），用于左侧导航栏和路由生成
        fetchMenuTree().catch(error => {
          console.error('[PermissionStore] 加载菜单树失败:', error)
          return { code: 200, data: [] }
        })
      ])
        .then(([permissionResponse, menuResponse]) => {
          // 处理用户权限（扁平化数组）
          let permissionCodes: string[] = []
          if (permissionResponse?.code === 200 && permissionResponse.data) {
            // 直接使用返回的扁平化权限数组
            permissionCodes = permissionResponse.data.permissions || []
            this.setPermissions(permissionCodes)
          } else {
            // 如果权限加载失败，设置默认权限
            this.setPermissions(['*'])
          }
          
          // 处理菜单树
          let menuTree: any[] = []
          if (menuResponse?.code === 200 && menuResponse.data) {
            menuTree = menuResponse.data
            this.setMenuTree(menuTree)
            
            // 从菜单树生成可访问路由
            this.generateRoutesFromMenu(menuTree)
          } else {
            // 如果菜单树加载失败，使用空数组
            this.setMenuTree([])
          }
          
          return {
            permissions: this.permissions,
            menuTree: this.menuTree
          }
        })
        .catch(error => {
          console.error('[PermissionStore] 加载权限失败:', error)
          
          // 根据错误类型显示不同的提示
          const status = error?.response?.status
          const errorMessage = error?.response?.data?.message || error?.message
          
          if (status === 403) {
            // 权限不足
            ElMessage.warning('权限不足，无法加载权限数据。请联系管理员分配相应角色。')
          } else if (status === 401) {
            // 未授权，需要重新登录
            ElMessage.error('登录已过期，请重新登录')
          } else if (status === 404) {
            // 接口不存在
            ElMessage.error('权限接口不存在，请检查后端服务')
          } else if (errorMessage) {
            // 显示后端返回的具体错误信息
            ElMessage.error(`加载权限失败: ${errorMessage}`)
          } else {
            // 网络错误或其他未知错误
            ElMessage.error('加载权限失败，请检查网络连接或稍后重试')
          }
          
          // 不阻止用户访问，使用空权限继续
          // 设置默认权限，确保基本功能可用
          this.setPermissions(['*'])
          this.setMenuTree([])
          
          return { permissions: ['*'], menuTree: [] }
        })
        .finally(() => {
          this.isLoadingPermissions = false
          // 请求完成后清除缓存
          setTimeout(() => { permissionsPromise = null }, 0)
        })
      
      return permissionsPromise
    },
    
    /**
     * 从权限树中提取权限码（优化版本）
     * 使用迭代而非递归，性能更好
     * @param tree 权限树
     * @returns 权限码数组
     */
    extractPermissionCodes(tree: any[]): string[] {
      if (!tree || !Array.isArray(tree) || tree.length === 0) return []
      
      const codes: string[] = []
      const stack = [...tree] // 使用栈进行迭代遍历
      
      while (stack.length > 0) {
        const node = stack.pop()!
        
        if (node.code) {
          codes.push(node.code)
        }
        
        // 将子节点加入栈中
        if (node.children && Array.isArray(node.children) && node.children.length > 0) {
          stack.push(...node.children)
        }
      }
      
      return codes
    },
    
    /**
     * 扁平化权限树为数组
     * @param tree 权限树
     * @param includeChildren 是否保留children字段，默认false
     * @returns 扁平化后的权限数组
     */
    flattenPermissionTree(tree: any[], includeChildren: boolean = false): any[] {
      if (!tree || !Array.isArray(tree) || tree.length === 0) return []
      
      const result: any[] = []
      const stack = [...tree]
      
      while (stack.length > 0) {
        const node = stack.pop()!
        const nodeCopy = { ...node }
        
        if (!includeChildren && nodeCopy.children) {
          delete nodeCopy.children
        }
        
        result.push(nodeCopy)
        
        if (node.children && Array.isArray(node.children) && node.children.length > 0) {
          stack.push(...node.children)
        }
      }
      
      return result
    },
    
    /**
     * 将扁平数组转换为树形结构
     * @param flatArray 扁平数组
     * @param idKey ID字段名，默认'id'
     * @param parentIdKey 父ID字段名，默认'parentId'
     * @param childrenKey 子节点字段名，默认'children'
     * @returns 树形结构
     */
    arrayToTree(
      flatArray: any[],
      idKey: string = 'id',
      parentIdKey: string = 'parentId',
      childrenKey: string = 'children'
    ): any[] {
      if (!flatArray || !Array.isArray(flatArray) || flatArray.length === 0) return []
      
      // 使用Map提升查找性能
      const nodeMap = new Map<any, any>()
      const childrenMap = new Map<any, any[]>()
      const tree: any[] = []
      
      // 第一遍遍历：建立节点映射
      for (const item of flatArray) {
        const itemId = item[idKey]
        const itemParentId = item[parentIdKey]
        
        const node = { ...item }
        delete node[childrenKey] // 移除可能存在的children字段
        nodeMap.set(itemId, node)
        
        // 建立父子关系映射
        if (!childrenMap.has(itemParentId)) {
          childrenMap.set(itemParentId, [])
        }
        childrenMap.get(itemParentId)!.push(node)
      }
      
      // 第二遍遍历：构建树结构
      for (const item of flatArray) {
        const itemId = item[idKey]
        const itemParentId = item[parentIdKey]
        const node = nodeMap.get(itemId)
        
        // 如果父节点不存在，则为根节点
        if (!itemParentId || !nodeMap.has(itemParentId)) {
          tree.push(node)
        }
        
        // 设置子节点
        const childrenList = childrenMap.get(itemId)
        if (childrenList && childrenList.length > 0) {
          node[childrenKey] = childrenList
        }
      }
      
      return tree
    },
    
    /**
     * 根据ID在权限树中查找节点
     * @param tree 权限树
     * @param id 要查找的ID
     * @returns 找到的节点，未找到返回null
     */
    findNodeInTree(tree: any[], id: number | string): any | null {
      if (!tree || !Array.isArray(tree) || tree.length === 0) return null
      
      const stack = [...tree]
      
      while (stack.length > 0) {
        const node = stack.pop()!
        
        if (node.id === id) {
          return node
        }
        
        if (node.children && Array.isArray(node.children) && node.children.length > 0) {
          stack.push(...node.children)
        }
      }
      
      return null
    },
    
    /**
     * 加载按钮级权限
     * @param menuId 菜单ID
     * @param path 菜单路径
     */
    async loadButtonPermissions(menuId: string | number, path: string) {
      // 如果已加载过该菜单的按钮权限，则跳过
      if (this.loadedMenuIds.has(menuId)) return
      
      try {
        // 调用API获取按钮权限
        const response = await fetchButtonPermissions(menuId)
        
        if (response && response.code === 200) {
          const buttonPermissions = response.data || []
          const buttonCodes = buttonPermissions.map((btn: any) => btn.code)
          
          // 更新按钮权限
          this.buttonPermissions[path] = buttonCodes
          
          // 标记为已加载
          this.loadedMenuIds.add(menuId)
        }
      } catch (error) {
        console.error(`加载菜单${menuId}的按钮权限失败:`, error)
      }
    },
    
    /**
     * 设置权限
     * @param permissions 权限列表
     */
    setPermissions(permissions: string[]) {
      this.permissions = permissions
      storage.set('permissions', permissions)
    },
    
    /**
     * 设置菜单树
     * @param menuTree 菜单树
     */
    setMenuTree(menuTree: any[]) {
      this.menuTree = menuTree
      storage.set('menuTree', menuTree)
    },
    
    /**
     * 设置可访问路由
     * @param routes 路由配置
     */
    setAccessRoutes(routes: RouteRecordRaw[]) {
      this.accessRoutes = routes
    },
    
    /**
     * 清除权限相关数据
     */
    clearPermissions() {
      this.permissions = []
      this.accessRoutes = []
      this.menuTree = []
      this.buttonPermissions = {}
      this.loadedMenuIds.clear()
      storage.remove('permissions')
      storage.remove('menuTree')
      if (typeof localStorage !== 'undefined') {
        localStorage.removeItem('vue-base-permissions')
      }
    },
    
    /**
     * 从菜单树生成路由配置
     * @param menuTree 菜单树
     * @returns 路由配置
     */
    generateRoutesFromMenu(menuTree: MenuItem[]): RouteRecordRaw[] {
      // 用于存储已使用的路由名称，避免重复
      const usedNames = new Set<string>()
      
      const generateRoutes = (menus: MenuItem[], parentPath = ''): CustomRouteRecordRaw[] => {
        if (!menus || menus.length === 0) return []
        
        return menus
          .filter(menu => menu.type === 'MENU')
          .map(menu => {
            const path = menu.path?.startsWith('/') ? menu.path : `${parentPath}/${menu.path || ''}`
            
            // 生成唯一的路由名称
            let routeName = menu.name || menu.code || path
            
            // 如果名称已存在，添加ID作为后缀确保唯一性
            if (usedNames.has(routeName)) {
              routeName = `${routeName}_${menu.id}`
            }
            usedNames.add(routeName)
            
            const route: CustomRouteRecordRaw = {
              path,
              name: routeName,
              meta: {
                title: menu.name,
                icon: menu.icon,
                keepAlive: menu.keepAlive,
                hidden: !menu.show,
                sort: menu.order,
                permission: menu.code,
                menuId: menu.id // 添加菜单ID到路由元数据，用于加载按钮权限
              },
              component: this.resolveComponent(menu.component)
            }
            
            // 处理子路由
            if (menu.children && menu.children.length > 0) {
              route.children = generateRoutes(menu.children, path)
            }
            
            return route
          })
      }
      
      const generatedRoutes = generateRoutes(menuTree) as unknown as RouteRecordRaw[]
      this.setAccessRoutes(generatedRoutes)
      return generatedRoutes
    },
    
    /**
     * 解析组件路径
     * @param component 组件路径
     * @returns 组件导入函数
     */
    resolveComponent(component?: string) {
      if (!component) {
        return () => import('../views/404.vue')
      }
      
      if (component === 'Layout') {
        // 使用已有的布局组件
        return () => import('../views/HomeView.vue')
      }
      
      try {
        // 处理组件路径，移除前导的 /src/
        const componentPath = component.replace(/^\/src\//, '../')
        return () => import(/* @vite-ignore */ componentPath)
      } catch (error) {
        console.warn(`组件 ${component} 不存在`, error)
        // 使用404组件作为后备
        return () => import('../views/404.vue')
      }
    }
  }
}) 